
using namespace std; 
  #include <iostream>
  #include <fstream>
  #include <cstdlib>
  #include <cstdio>
  //#include <ctype>
  #include <string>
  #include <cmath>
  #include <cfloat>
  #include <cstring>
  #include <list>
  

  
  #include "../evo/evolimits.h"
  #include "../evo/mylib.h"
  //#include "../evo/gb/gblimits.h"
  //#include "../evo/gb/gb_evo.h"
 // #include "../evo/ga/galimits.h"
 // #include "../evo/ga/ga_evo.h"
  
  

   
  #define EXP_SEP "$"
  // E' il simbolo scelto per separare le espressioni
  
  #define NULL_VALUE -9876543210.0123456789
  // E' un numero "magico" da attribuire alle feature non valide.
  
  #define ZERO_VALUE 0.0
  //  E' il valore zero nel problema da risolvere.
  
  #define MAX_FEATURES  70
  /// E' il numero di features presenti nel features vector.
 
  #define MAX_ITEMS 10000 
  // E' il numero di items presenti nel Data Set.
  
  #define MAX_CLUSTERS 100
  // E' il numero massimo di clusters consentiti. 
  
  #define MIN_CLUSTERS 2
  // E' il numero minimo di clusters consentiti. 
  
  #define MAX_CLASSES  10
  // E' il massimo numero di classi previsto.

  #define NORM_FACTOR 3.0
  // E' il fattore x il quale viene divisa la deviaz. std (NORMALIZZAZIONE)
   
  #define DEFAULT_DATA_FILE  "data.txt"
  // E' il nome del file di default che contiene i dati da caricare.
  
  #define DEFAULT_TRAIN_FILE  "train.dat"
  // E' il nome del file di default per il train set.
  
  #define DEFAULT_TEST_FILE  "test.dat"
  // E' il nome del file di default per il test set.
  

  typedef struct data_item {
             double vector[MAX_FEATURES];
             int cluster;
          };
  /* E' il vettore che contiene gli items del Data Set.
  */
  
    typedef struct range {
             double avg, dev;
          };
  /* E' il vettore che contiene gli items del Data Set.
  */
  enum assign_type {null, match, neigh};
  /* Questa enumerazione � stata definita per denotare i 2 tipi possi-
     bili di assegnazione per un item del Data Set.
  */

  typedef struct memo_item {
             assign_type assign;
             int cluster;
          };
 
  /* Questa struttura � utilizzata per costruire il vettore clustering,
     che si trova nella classe Individual. Essa rappresenta un item del
     data set e memorizza a quale cluster � stato assegnato e con che
     tipo di assegnamento.
  */
  
   
  typedef struct dist_row{
      double *cols;
  };
  /* Questa struttura contiene un puntatore ad un double ed e' utilizzata
     per costuire la matrice delle distanze.      
  */ 
  
  
  /*
  ++++++++++++++++++++++++ Classe DATA ++++++++++++++++++++++++++++++++++++
  
  Questa classe contiene tutte le informazioni relative ai data set utiliz-
  zati in problemi di data mining e machine learning.
  */
  class Data
  {
  public:
     Data();
     /* E' la costruttrice della classe e' vuota.
     */
     string give_data_name();
     /* Restituisce il nome del file che contiene i dati.
     */     
     string give_train_name();
     /* Restituisce il nome del file che contiene il  train set.
     */
     string give_test_name();
     /* Restituisce il nome del file che contiene il  test set.
     */
     int give_classes_num();
     /* Restituisce il numero di classi effettive del problema.
     */
     int give_features_num();
     /* Restituisce il numero di features dei dati.
     */     
     int give_train_num();
     /* Restituisce il numero di items nel train set. 
     */
     int give_test_num();
     /* Restituisce il numero di items nel test set. 
     */
     int give_k_value();
     /* Restituisce il k della fold validation utlizzata. 
     */
     bool testing (){return test;}
     /* Restituisce TRUE se c'è il test.*/
     bool is_all(){ return all;}
     
     double give_train_range(int index);
     /* Restituisce il valore dev dell'elemento di indice index del vettore 
        ranges. Questo vettore contiene i range delle features del train
        set.
     */
     double give_train_aver(int index);
     /* Restituisce il valore ave dell'elemento di indice index del vettore 
        ranges. Questo vettore contiene i range delle features del train
        set.
     */
     double give_test_range(int index);
     /* Restituisce il valore dev dell'elemento di indice index del vettore 
        ranges. Questo vettore contiene i range delle features del test 
        set.
     */
     double give_test_aver(int index);
     /* Restituisce il valore ave dell'elemento di indice index del vettore 
        ranges. Questo vettore contiene i range delle features del test
        set.
     */
     void give_train_item(double *vec);
     /* Copia nel parametro passato un item del training set scelto in ma-
        niera random.
     */ 
     void give_train_item(double vec[], int index);
     /* Copia nel parametro passato l'item di indice index.
     */ 
     void show_train_item(ostream *out_stream, int index);
     /* Visualizza l'item passato come parametro.
      */
     void show_test_item(ostream *out_stream, int index);
     /* Visualizza l'item passato come parametro.
      */
     void get_params(int argc, char *argv[], bool visual);
     /* Questa procedura legge da file tutti i parametri relativi al prob-
        lema in esame. Prende come parametri la riga di comando, per leg-
        gere le eventuali informazioni passate dall'utente. Il terzo para-
        metro specifica se visulalizzare un messaggio di corretta acquisi-
        zione dei dati.
     */
     void give_params(ofstream *out_stream);
     /* Scrive tutti i parametri dell'evoluzione nel file passato come para-
        metro. 
     */
     double comp_vectors_dist (double vector_1[],  double vector_2[]);
     /* Calcola la distanza tra i due vettori passati come parametri. Il
        tipo di distanza calcolata  dipende dal parametro dist_type defini-
        to all'interno della classe.
     */
     double comp_train_dist(double vector[], int index);
     /* Calcola la distanza tra il vettore passato come parametro e l'item 
        del train set di indice index, */
     double comp_train_dist_fast(double vector[], int index, 
                                 double min_dist);
     /* Calcola la distanza tra il vettore passato come parametro e l'item 
        del train set di indice index, in maniera tale da ridurre la com-
        plessita' computazionale. Il terzo parametro specifica una dis-
        tanza minima di riferimento, da utilizzare per terminare i calcoli
        in anticipo.   */
     double comp_test_dist(double vector[], int index);
     /* Calcola la distanza tra il vettore passato come parametro e l'item 
        del test set di indice index. 
     */
     int give_train_item(int index);
     /* Restituisce la classe di appartenenza dell'item di indice index del
        train set. 
     */
      int give_test_item(int index);
     /* Restituisce la classe di appartenenza dell'item di indice index del
        test set. 
     */
     int give_dist_train(int index){return dist_train[index];}
     /* Restituisce il numero di sample del TRAIN SET della classe index.
      */
     void comp_dist_train(); 
     /* Calcola la distribuzione delle classi del train set. 
      */
     double give_dist_type();
     /* Ritorna il tipo di distanza utilizzato nei calcoli per le distanze,
        nello spazio euclideo.
     */
     bool valid_feature(int index){return valid_features[index];};
     /* Restituisce la validita' della feature passata come parametro.
     */ 
     double give_matrix_elem(int train_index, int test_index)
            { return dist_matrix[train_index].cols[test_index];};
     /* Restituisce l'elemento (i,j) della matrice delle distanze tra train
        e test set. 
     */
     void build_dist_matrix();
     /* Costruisce la matrice delle distanze tra test e train set. 
     */                       
      void load_train_set(); 
     /* Costruisce l'array del train set e lo carica da file. 
     */ 
     void load_test_set(); 
     /* Costruisce l'array del test set e lo carica da file. 
     */ 
     
     data_item *train_set;  
     /* E' l'array che contiene il train set. Viene costruito DINAMICAMEN-
        TE!
     */
     data_item *test_set;
     /* E' l'array che contiene il test set. Viene costruito DINAMICAMENTE!
     */
     data_item *data_set;
     /* E' l'array che contiene il data set totale. Viene costruito DINAMICAMENTE!
     */
     void build_sets();
     /* Costruisce train e test set.
     */
  protected:
     
     void comp_train_ranges();
     /* Calcola ed inizializza i ranges delle features del train set.
     */
     void comp_test_ranges();
     /* Calcola ed inizializza i ranges delle features del test set.
     */
     void normalize();
     /* Normalizza i vettori presenti nel train set. Applicando la seguente 
        formula: 
                   Vnorm[i] = (V[i] - Vmedio[i]) / N_train.
      */
     bool extract_param(char *line);
     /* Estrae dalla linea passata come parametro gli attributi della clas-
        se.
     */
     void get_no_features(char *line_ptr);
     /* Acquisisce dalla riga passata come parametro le features non vali-
     de.
     */
     void load_data();
     /* Carica il dataset totale e crea train e test set.
     */     
     void load_data_set(ifstream *in_stream, data_item *data_set, 
                           int item_num);
     /* Carica nell'array passato come secondo parametro il data set presen-
        te nel  file passato come primo parametro. Il terzo parametro speci-
        fica il numero di item da caricare. 
     */
     void load_data_set2(ifstream *in_stream, data_item *data_set, 
                           int item_num);
     /* Carica nell'array passato come secondo parametro il data set presen-
        te nel  file passato come primo parametro. Il terzo parametro speci-
        fica il numero di item da caricare. Si differenzia dalla precedente
        dal formato di memorizzazione dei dati. 
     */     
     void comp_dist_matrix();
     /* Calcola la matrice delle distanze tra train e test set.
     */                           
     char data_file_name[MAX_CHAR_FILE_NAME];
     /* E' il nome del file che contiene i parametri per i dati.
     */
     char train_file_name[MAX_CHAR_FILE_NAME];
     /* E' il nome del file che contiene il  train set.
     */
     char test_file_name[MAX_CHAR_FILE_NAME];
     /* E' il nome del file che contiene il  test set.
     */
     char data_set_name[MAX_CHAR_FILE_NAME];
     /* E' il nome del file che contiene il data set totale.
     */
     int classes_num;
     /* E' il numero di classi effettive del problema.
     */
     int features_num;
     /* E' il numero di features dei dati.
     */     
     int train_num;
     /* E' il numero di items nel train set. 
     */
     int test_num;
     /* E' il numero di items nel test set. 
     */
     double train_per;
     /* E' la percentuale di items da estrarre dal dataset totale da assegnare al train set. 
     */     
     int data_num;
     /* E' il numero di items nel data set totale.
     */
     int k_value;
     /* Questa variabile indica il valore di k utilizzato per il validation
        test utilizzato. 
     */
     bool test;
     /* Questa variabile indica la presenza del test set.
     */
     bool all;
     /* Questa variabile indica la presenza di un dataset unico dal quale estrarre 
        casaualmente train e test set. 
     */
     
     struct range train_ranges[MAX_FEATURES];
     /* E' l'array che contiene i ranges delle features del train set.
     */
     struct range test_ranges[MAX_FEATURES];
     /* E' l'array che contiene i ranges delle features del test set.
     */
     bool valid_features[MAX_FEATURES];
     /* E' l'array che cotniene l'informazione sulle features da non consi-
        derare.
     */
     dist_row *dist_matrix;
     /* E' il puntatore alla matrice delle distanze tra train e test set.
        ATTENZIONE!: La matrice contiene un numero di righe pari alle dimen-
        sioni del TRAIN SET e un numero di colonne pari alle dimensioni del 
        TEST SET.
     */
     int dist_train[MAX_CLASSES];
     /* Memorizza la distribuzione delle classi.
      */
     double dist_type;
     /* E' il tipo di distanza utilizzata nel problema.
     */
     int N_params;
     /* E' il numero di parametri passato dall'utente.
     */
     bool special_format;
     /* Specifica se il formato dei dati e' quello speciale oppure no.
     */
     bool char_format;
     /* Specifica se il formato dei dati e' quello specifico dei caratteri. 
     */
      
  };   


   /*
  ++++++++++++++++++++++++ Classe CLUSTER +++++++++++++++++++++++++++++++++
  *** Definita il: 

  La classe Cluster rappresenta un cluster di una clusterizzazione. Esso
  � rappresentato da un'espressione logico-matematica che esprime i va-
  lori assunti dalle features degli items ceh appartengono al cluster.
  Inoltre, il cluster contiene i vari centroidi calcolati sui vari tipi
  di items assegnati alla cluster.*/

  class Cluster
  {
  public:
     Cluster ();
     /* E' la procedura costruttrice della classe. Serve per allocare og-
        getti della classe. */
     Cluster (int position);
     /* E' la procedura costruttrice della classe. IL parametro specifica
        la sua posizione all'interno del vettore di clusters che si trova
        nella classe Individual.
        */
     int give_label(){return label;};
     /* Restituisce la label assegnata al cluster.
     */
     float give_cover(){return cover;};
     /* Restituisce la copertura del data set del cluster.
     */
     int give_cover(int cl){return cover_nums[cl];}
     /* Restituisce il numero di items della cl-esima classe coperta dal 
        cluster. 
     */
    // Gene *gene_ptr;
     /* Punta al gene relativo al cluster. 
     */
     void update_clustering(bool *clustering);
     /* Aggiorna il clustering passato come parametro aggiungendovi gli 
        items assegnati al cluster. 
     */
     float comp_clustering_dist(bool *clustering);
     /* Calcola la distanza tra il clustering passato come individuo e il 
        vettore di assegnazione dell'individuo. 
     */
     float give_centroid_elem(int index){return centroid[index];};
     /* Restituisce l'elemento di indice index del centroide del cluster.
     */
     float give_centroids_elem(int cl, int index){
           return centroids[cl][index];};
     /* Restituisce l'elemento di indice index del centroide degli items 
        della classe cl assegnati al cluster.
     */  
     int  give_clauses(){return clauses_number;};
     /* Memorizza il numero di clausole presenti nell'espressione.
      */
      string give_expression(){return expression;};
     /* Restituisce la stringa del cluster.
      */
      void get_expression(char *str_ptr){expression=str_ptr;};
     /* Memorizza nella stringa expression la stringa passata come para-
      * metro. 
      */
      void get_number(int num){number = num;};
     /* Memorizza la variabile number.
      */
      void get_clauses(int num){clauses_number = num;};
     /* Memorizza il numero di clausole presenti nell'espressione.
      */
      void get_cover(double cov){cover = cov;};
      /* Memorizza la percentuale di corretta classificazioen del cluster.
       */
      void get_label(int l){label = l;};
      /* Memorizza la label del clsuter.
       */

      
         
  private:
               
     int number;
     /* Questa variabile specifica la posizione del cluster nel vettore.
     */
     double centroid[MAX_FEATURES];
     /* E' il centroide degli items assegnati al cluster.
     */     
     double centroids[MAX_CLASSES][MAX_FEATURES];
     /* Sono i centroidi degli items della stessa classe assegnati al clus-
        ter. */
     double cover; 
     /* E' la percentuale di copertura rappresentata dal cluster.
     */
     string expression;
     /* E' l'espressione che rappresenta il cluster è un espressione di ti-
        po logico matematica.
     */
     int cover_nums[MAX_CLASSES];
     /* Questo vettore memorizza la situazione di copertura delle varie cl-
        assi. Es. in cover_nums[i] sono memorizzati il numero di items del-
        la i-esima classe assegnati al cluster. 
        */     
     int label;
     /* E' la label assegnata al cluster.
     */
     int clauses_number;
     /* E' il numero di clausole presenti nell'espressione.
      */
   
     
     

     friend class char_Individual;
     friend ostream &operator<<(ostream &stream, Cluster clust);
    // friend ostream &operator<<(ostream &stream, cls_Individual ind);
   };

   // ******************* INSERITORE della classe Cluster ***************
   ostream &operator<<(ostream &stream, Cluster clust);
     /* Stampa su file, tutti i dati del cluster.
     */

